/**
 * @file port_uart.c
 * @brief
 * @author lijingjie (lijingjie@pthyidh.com)
 * @date 2024-11-05 01:46:48
 *
 * @copyright Copyright (c) 2024 by 深圳市鹏天微智能科技有限公司, All Rights Reserved.
 */

/* ==================== [Includes] ========================================== */

#include "xf_hal_port.h"
#if XF_HAL_UART_IS_ENABLE
#include <stdio.h>
#include <stdlib.h>

#include "pt3220.h"
#include "drvs.h"

#include "xf_utils.h"
#include "xf_init.h"
#include "utils/port_xf_ringbuf.h"

/* ==================== [Defines] =========================================== */

#define XF_HAL_UART_DEFAULT_DATA_BITS       XF_HAL_UART_DATA_BIT_8
#define XF_HAL_UART_DEFAULT_STOP_BITS       XF_HAL_UART_STOP_BIT_1
#define XF_HAL_UART_DEFAULT_PARITY_BITS     XF_HAL_UART_PARITY_BITS_NONE
#define XF_HAL_UART_DEFAULT_FLOW_CONTROL    XF_HAL_UART_FLOW_CONTROL_NONE
#define XF_HAL_UART_DEFAULT_BAUDRATE        115200
#define XF_HAL_UART_DEFAULT_TX_NUM          8
#define XF_HAL_UART_DEFAULT_RX_NUM          9
#define XF_HAL_UART_DEFAULT_RTS_NUM         -1
#define XF_HAL_UART_DEFAULT_CTS_NUM         -1

#define UART_DEFAULT_FIFO_RXTL 8

#if defined(CONFIG_RINGBU_SIZE)
    #define RINGBU_LEN     (CONFIG_RINGBU_SIZE)
#else
    #define RINGBU_LEN     (0x100)
#endif

#define TAG   ("PORT_UART")

enum
{
    UART_PORT_1 = 0,
    UART_PORT_2,

    UART_PORT_MAX
};

/* ==================== [Typedefs] ========================================== */

/**
 * @brief uart 状态结构体。
 */
typedef struct _port_uart_obj_t
{
    xf_ringbuf_t rb_rx; /*!< UART RX 缓冲区句柄 */
} port_uart_obj_t;

/* ==================== [Static Prototypes] ================================= */

/* ==================== [Static Variables] ================================== */

port_uart_obj_t *sp_uart_obj[UART_PORT_MAX];

/* ==================== [Macros] ============================================ */

/* ==================== [Global Functions] ================================== */
static void _port_uart_rb_read(uint8_t port)
{
    uint32_t state = uart_intr_mask_get(port); // UART1->RIF.Word;

    if (UART_IR_RXRD_BIT & state) //(BIT_RXRD)
    {
        uart_intr_disable(port, UART_IR_RXRD_BIT); // Disable RXRD Interrupt

        for (uint8_t i = 0; i < UART_DEFAULT_FIFO_RXTL; i++)
        {
            uint8_t data = uart_getc(port);
            xf_ringbuf_write(&sp_uart_obj[port]->rb_rx, &data, 1);
        }

        uart_intr_clr(port, UART_IR_RXRD_BIT); // Clear RXRD Interrupt Flag
        uart_intr_enable(port, UART_IR_RXRD_BIT); // Enable RXRD Interrupt
    }

    if (UART_IR_RTO_BIT & state) //(BIT_RTO)
    {
        uart_intr_disable(port, UART_IR_RTO_BIT); // Disable RTO Interrupt

        while (uart_sta_mask_get(port) & UART_SR_RFNE_BIT)
        {
            uint8_t data = uart_getc(port);
            xf_ringbuf_write(&sp_uart_obj[port]->rb_rx, &data, 1);
        }

        uart_intr_clr(port, UART_IR_RTO_BIT); // Clear RTO Interrupt Flag
        uart_intr_enable(port, UART_IR_RTO_BIT); // Enable RTO Interrupt
    }
}

// 串口1中断
void UART1_IRQHandler(void)
{
    _port_uart_rb_read(UART_PORT_1);
}

// 串口2中断
void UART2_IRQHandler(void)
{
    _port_uart_rb_read(UART_PORT_2);
}

/* ==================== [Static Functions] ================================== */
static int _xf_uart_gets(uint8_t port, char *buffer, int buffer_size)
{
    if (buffer_size == 0 || buffer == NULL)
    {
        return -1;
    }
    uint16_t get_size = xf_ringbuf_get_count(&sp_uart_obj[port]->rb_rx);
    get_size = get_size > buffer_size ? buffer_size : get_size;
    xf_ringbuf_read(&sp_uart_obj[port]->rb_rx, buffer, get_size);
    return get_size;
}


// 外部调用的接口
static xf_err_t port_uart_open(xf_hal_dev_t *dev)
{
    if (dev->id >= UART_PORT_MAX)
    {
        return XF_ERR_INVALID_ARG;
    }
    sp_uart_obj[dev->id] = xf_malloc(sizeof(port_uart_obj_t));
    if (NULL == sp_uart_obj[dev->id])
    {
        return XF_ERR_NO_MEM;
    }
    xf_memset(&sp_uart_obj[dev->id]->rb_rx, 0, sizeof(xf_ringbuf_t));
    sp_uart_obj[dev->id]->rb_rx.p_buf = xf_malloc(RINGBU_LEN);
    if (NULL == sp_uart_obj[dev->id]->rb_rx.p_buf)
    {
        return XF_ERR_NO_MEM;
    }
    xf_memset(sp_uart_obj[dev->id]->rb_rx.p_buf, 0, RINGBU_LEN);
    sp_uart_obj[dev->id]->rb_rx.buf_size = RINGBU_LEN;


    return XF_OK;
}

static xf_err_t port_uart_ioctl(xf_hal_dev_t *dev, uint32_t cmd, void *config)
{
    xf_hal_uart_config_t *uart_config = (xf_hal_uart_config_t *)config;
    static uint16_t cfg = 0;

    if (cmd == XF_HAL_UART_CMD_DEFAULT) {
        uart_config->data_bits      = XF_HAL_UART_DEFAULT_DATA_BITS;
        uart_config->stop_bits      = XF_HAL_UART_DEFAULT_STOP_BITS;
        uart_config->parity_bits    = XF_HAL_UART_DEFAULT_PARITY_BITS;
        uart_config->flow_control   = XF_HAL_UART_DEFAULT_FLOW_CONTROL;
        uart_config->baudrate       = XF_HAL_UART_DEFAULT_BAUDRATE;
        uart_config->tx_num         = XF_HAL_UART_DEFAULT_TX_NUM;
        uart_config->rx_num         = XF_HAL_UART_DEFAULT_RX_NUM;
        uart_config->rts_num        = XF_HAL_GPIO_NUM_NONE;
        uart_config->cts_num        = XF_HAL_GPIO_NUM_NONE;

        return XF_OK;
    }

    if (cmd == XF_HAL_UART_CMD_ALL) {
        return XF_OK;
    }

    if ((cmd & XF_HAL_UART_CMD_BAUDRATE) || (cmd & XF_HAL_UART_CMD_DATA_BITS) || (cmd & XF_HAL_UART_CMD_STOP_BITS)
        || (cmd & XF_HAL_UART_CMD_PARITY_BITS)) {
        uint16_t data_bits = 0;
        uint16_t stop_bits = 0;
        uint16_t parity_bits = 0;

        switch (uart_config->data_bits) {
        case XF_HAL_UART_DATA_BIT_5:
            data_bits = LCD_DATA_BITS_5;
            break;
        case XF_HAL_UART_DATA_BIT_6:
            data_bits = LCD_DATA_BITS_6;
            break;
        case XF_HAL_UART_DATA_BIT_7:
            data_bits = LCD_DATA_BITS_7;
            break;
        case XF_HAL_UART_DATA_BIT_8:
            data_bits = LCD_DATA_BITS_8;
            break;
        case XF_HAL_UART_DATA_BIT_9:
            XF_LOGE(TAG, "data_bits 9 not support");
            return XF_ERR_INVALID_ARG;

        default:
            break;
        }

        switch (uart_config->stop_bits) {
        case XF_HAL_UART_STOP_BIT_1:
            stop_bits = LCR_STOP_BITS_1;
            break;
        case XF_HAL_UART_STOP_BIT_1_5:
            XF_LOGE(TAG, "stop_bits 1.5 not support");
            return XF_ERR_INVALID_ARG;
        case XF_HAL_UART_STOP_BIT_2:
            stop_bits = LCR_STOP_BITS_2;
            break;

        default:
            break;
        }

        switch (uart_config->parity_bits) {
        case XF_HAL_UART_PARITY_BITS_NONE:
            parity_bits = LCR_PARITY_none;
            break;
        case XF_HAL_UART_PARITY_BITS_EVEN:
            parity_bits = LCR_PARITY_even;
            break;
        case XF_HAL_UART_PARITY_BITS_ODD:
            parity_bits = LCR_PARITY_odd;
            break;
        case XF_HAL_UART_PARITY_BITS_SPACE:
            XF_LOGE(TAG, "parity_bits space not support");
            break;
        case XF_HAL_UART_PARITY_BITS_MARK:
            XF_LOGE(TAG, "parity_bits mark not support");
            break;

        default:
            break;
        }

        cfg = data_bits | stop_bits | parity_bits;
        uart_conf(dev->id, uart_config->baudrate, cfg);
    }

    if ((cmd & XF_HAL_UART_CMD_TX_NUM) || (uart_config->enable)) {
        csc_output(uart_config->tx_num, CSC_UART1_TXD + dev->id * 2);
    }

    if ((cmd & XF_HAL_UART_CMD_RX_NUM) || (uart_config->enable)) {
        csc_input(uart_config->rx_num,  CSC_UART1_RXD + dev->id * 2);
    }

    if ((cmd & XF_HAL_UART_CMD_CTS_NUM) || (cmd & XF_HAL_UART_CMD_RTS_NUM)) {
        if (uart_config->flow_control == XF_HAL_UART_FLOW_CONTROL_RTS_CTS) {
            uart_hwfc(dev->id, uart_config->rts_num, uart_config->cts_num);
        }
    }

    if (cmd & XF_HAL_UART_CMD_ENABLE) {
        if (uart_config->enable) {
            uart_init(dev->id, uart_config->tx_num, uart_config->rx_num);
            uart_conf(dev->id, BRR_BAUD(uart_config->baudrate), cfg);
            uart_fctl(dev->id, FCR_FIFOEN_BIT | FCR_RXTL_8BYTE,
              20 /*bits_rto*/, UART_IR_RXRD_BIT | UART_IR_RTO_BIT); // 20个字节的时间没有数据，就认为接收超时。
            IRQn_Type UART_IRQ[] = {UART1_IRQn, UART2_IRQn};
            NVIC_EnableIRQ(UART_IRQ[dev->id]);
            XF_LOGD(TAG, "id:%d,%d,%d,%d, %d", dev->id, uart_config->tx_num, uart_config->rx_num, uart_config->baudrate, cfg);
        } else {
            uart_deinit(dev->id);
        }
    }

    return XF_OK;
}

static int port_uart_read(xf_hal_dev_t *dev, void *buf, size_t count)
{
    return _xf_uart_gets(dev->id, buf, count);
}

static int port_uart_write(xf_hal_dev_t *dev, const void *buf, size_t count)
{
    for (size_t i = 0; i < count; i++) {
        uart_putc(dev->id, ((uint8_t*)buf)[i]);
    }
    return count;
}

static xf_err_t port_uart_close(xf_hal_dev_t *dev)
{
    if (NULL != sp_uart_obj[dev->id])
    {
        xf_free(sp_uart_obj[dev->id]->rb_rx.p_buf);
        xf_free(sp_uart_obj[dev->id]);
        sp_uart_obj[dev->id] = NULL;
    }
    return XF_OK;
}

static int xf_hal_uart_reg(void)
{
    xf_driver_ops_t ops = {
        .open = port_uart_open,
        .ioctl = port_uart_ioctl,
        .write = port_uart_write,
        .read = port_uart_read,
        .close = port_uart_close,
    };
    xf_hal_uart_register(&ops);

    return XF_OK;
}

XF_INIT_EXPORT_PREV(xf_hal_uart_reg);

#endif
